<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="renderer" content="webkit">
    <script>
        "use strict";
        (function (_window) {
            var navigatorUserAgent = navigator.userAgent;
            var iPhone = navigatorUserAgent.indexOf("iPhone");
            if (iPhone > -1) {
                var dpr = Number(window.devicePixelRatio), one_dpr = 1 / dpr
            } else {
                var dpr = 1, one_dpr = 1
            }
            var writeText = "<meta name=\"viewport\" content=\"width=device-width,initial-scale=" + one_dpr + ",maximum-scale=" + one_dpr + ",minimum-scale=" + one_dpr + ",user-scalable=no\">\n        <meta name=\"'flexible\" content=\"initial-dpr=" + dpr + "\">";
            document.write(writeText);
            var html = document.getElementsByTagName("html");
            var F0 = 75;
            html[0].setAttribute("data-dpr", dpr);
            var getFontSize = function getFontSize() {
                var windowWidth = window.innerWidth;
                html[0].style.fontSize = F0 * windowWidth / 750 + "px"
            };
            getFontSize();
            _window.addEventListener("resize", getFontSize, false)
        })(window);
    </script>
    <style>
        body {
            margin: 0;
        }

        html, body, #CanvasBody {
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        #CanvasBody {
            position: relative;
        }

        #onDevice {
            position: absolute;
            bottom: 0;
            right: 0;
            z-index: 2;
            padding: 12px 18px;
            font-size: 20px;
            border: 1px solid #ddd;
            background-color: #fff;
            cursor: pointer;
            -webkit-appearance: none;
        }
    </style>
</head>
<body>
<div id="CanvasBody">
    <input id="onDevice" type="button" value="开启陀螺仪">
</div>
<script src="https://cdn.bootcss.com/three.js/r76/three.min.js"></script>
<script src="https://cdn.bootcss.com/stats.js/r16/Stats.min.js"></script>
<!-- 鼠标控制 （OrbitControls.js） -->
<script>
    THREE.OrbitControls = function (object, domElement) {
        this.object = object;
        this.domElement = (domElement !== undefined) ? domElement : document;
        this.enabled = true;
        this.target = new THREE.Vector3();
        this.minDistance = 0;
        this.maxDistance = Infinity;
        this.minZoom = 0;
        this.maxZoom = Infinity;
        this.minPolarAngle = 0;
        this.maxPolarAngle = Math.PI;
        this.minAzimuthAngle = -Infinity;
        this.maxAzimuthAngle = Infinity;
        this.enableDamping = false;
        this.dampingFactor = 0.25;
        this.enableZoom = true;
        this.zoomSpeed = 1.0;
        this.enableRotate = true;
        this.rotateSpeed = 1.0;
        this.enablePan = true;
        this.keyPanSpeed = 7.0;
        this.autoRotate = false;
        this.autoRotateSpeed = 2.0;
        this.enableKeys = true;
        this.keys = {LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40};
        this.mouseButtons = {ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT};
        this.target0 = this.target.clone();
        this.position0 = this.object.position.clone();
        this.zoom0 = this.object.zoom;
        this.getPolarAngle = function () {
            return phi
        };
        this.getAzimuthalAngle = function () {
            return theta
        };
        this.reset = function () {
            scope.target.copy(scope.target0);
            scope.object.position.copy(scope.position0);
            scope.object.zoom = scope.zoom0;
            scope.object.updateProjectionMatrix();
            scope.dispatchEvent(changeEvent);
            scope.update();
            state = STATE.NONE
        };
        this.update = function () {
            var offset = new THREE.Vector3();
            var quat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0));
            var quatInverse = quat.clone().inverse();
            var lastPosition = new THREE.Vector3();
            var lastQuaternion = new THREE.Quaternion();
            return function () {
                var position = scope.object.position;
                offset.copy(position).sub(scope.target);
                offset.applyQuaternion(quat);
                spherical.setFromVector3(offset);
                if (scope.autoRotate && state === STATE.NONE) {
                    rotateLeft(getAutoRotationAngle())
                }
                spherical.theta += sphericalDelta.theta;
                spherical.phi += sphericalDelta.phi;
                spherical.theta = Math.max(scope.minAzimuthAngle, Math.min(scope.maxAzimuthAngle, spherical.theta));
                spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));
                spherical.makeSafe();
                spherical.radius *= scale;
                spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));
                scope.target.add(panOffset);
                offset.setFromSpherical(spherical);
                offset.applyQuaternion(quatInverse);
                position.copy(scope.target).add(offset);
                scope.object.lookAt(scope.target);
                if (scope.enableDamping === true) {
                    sphericalDelta.theta *= (1 - scope.dampingFactor);
                    sphericalDelta.phi *= (1 - scope.dampingFactor)
                } else {
                    sphericalDelta.set(0, 0, 0)
                }
                scale = 1;
                panOffset.set(0, 0, 0);
                if (zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {
                    scope.dispatchEvent(changeEvent);
                    lastPosition.copy(scope.object.position);
                    lastQuaternion.copy(scope.object.quaternion);
                    zoomChanged = false;
                    return true
                }
                return false
            }
        }();
        this.dispose = function () {
            scope.domElement.removeEventListener('contextmenu', onContextMenu, false);
            scope.domElement.removeEventListener('mousedown', onMouseDown, false);
            scope.domElement.removeEventListener('mousewheel', onMouseWheel, false);
            scope.domElement.removeEventListener('MozMousePixelScroll', onMouseWheel, false);
            scope.domElement.removeEventListener('touchstart', onTouchStart, false);
            scope.domElement.removeEventListener('touchend', onTouchEnd, false);
            scope.domElement.removeEventListener('touchmove', onTouchMove, false);
            document.removeEventListener('mousemove', onMouseMove, false);
            document.removeEventListener('mouseup', onMouseUp, false);
            document.removeEventListener('mouseout', onMouseUp, false);
            window.removeEventListener('keydown', onKeyDown, false);
        };
        var scope = this;
        var changeEvent = {type: 'change'};
        var startEvent = {type: 'start'};
        var endEvent = {type: 'end'};
        var STATE = {NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5};
        var state = STATE.NONE;
        var EPS = 0.000001;
        var spherical = new THREE.Spherical();
        var sphericalDelta = new THREE.Spherical();
        var scale = 1;
        var panOffset = new THREE.Vector3();
        var zoomChanged = false;
        var rotateStart = new THREE.Vector2();
        var rotateEnd = new THREE.Vector2();
        var rotateDelta = new THREE.Vector2();
        var panStart = new THREE.Vector2();
        var panEnd = new THREE.Vector2();
        var panDelta = new THREE.Vector2();
        var dollyStart = new THREE.Vector2();
        var dollyEnd = new THREE.Vector2();
        var dollyDelta = new THREE.Vector2();

        function getAutoRotationAngle() {
            return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed
        }

        function getZoomScale() {
            return Math.pow(0.95, scope.zoomSpeed)
        }

        function rotateLeft(angle) {
            sphericalDelta.theta -= angle
        }

        function rotateUp(angle) {
            sphericalDelta.phi -= angle
        }

        var panLeft = function () {
            var v = new THREE.Vector3();
            return function panLeft(distance, objectMatrix) {
                v.setFromMatrixColumn(objectMatrix, 0);
                v.multiplyScalar(-distance);
                panOffset.add(v)
            }
        }();
        var panUp = function () {
            var v = new THREE.Vector3();
            return function panUp(distance, objectMatrix) {
                v.setFromMatrixColumn(objectMatrix, 1);
                v.multiplyScalar(distance);
                panOffset.add(v)
            }
        }();
        var pan = function () {
            var offset = new THREE.Vector3();
            return function (deltaX, deltaY) {
                var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
                if (scope.object instanceof THREE.PerspectiveCamera) {
                    var position = scope.object.position;
                    offset.copy(position).sub(scope.target);
                    var targetDistance = offset.length();
                    targetDistance *= Math.tan((scope.object.fov / 2) * Math.PI / 180.0);
                    panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);
                    panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix)
                } else if (scope.object instanceof THREE.OrthographicCamera) {
                    panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix);
                    panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix)
                } else {
                    console.warn('WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.');
                    scope.enablePan = false
                }
            }
        }();

        function dollyIn(dollyScale) {
            if (scope.object instanceof THREE.PerspectiveCamera) {
                scale /= dollyScale
            } else if (scope.object instanceof THREE.OrthographicCamera) {
                scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));
                scope.object.updateProjectionMatrix();
                zoomChanged = true
            } else {
                console.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.');
                scope.enableZoom = false
            }
        }

        function dollyOut(dollyScale) {
            if (scope.object instanceof THREE.PerspectiveCamera) {
                scale *= dollyScale
            } else if (scope.object instanceof THREE.OrthographicCamera) {
                scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));
                scope.object.updateProjectionMatrix();
                zoomChanged = true
            } else {
                console.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.');
                scope.enableZoom = false
            }
        }

        function handleMouseDownRotate(event) {
            rotateStart.set(event.clientX, event.clientY)
        }

        function handleMouseDownDolly(event) {
            dollyStart.set(event.clientX, event.clientY)
        }

        function handleMouseDownPan(event) {
            panStart.set(event.clientX, event.clientY)
        }

        function handleMouseMoveRotate(event) {
            rotateEnd.set(event.clientX, event.clientY);
            rotateDelta.subVectors(rotateEnd, rotateStart);
            var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
            rotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed);
            rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed);
            rotateStart.copy(rotateEnd);
            scope.update()
        }

        function handleMouseMoveDolly(event) {
            dollyEnd.set(event.clientX, event.clientY);
            dollyDelta.subVectors(dollyEnd, dollyStart);
            if (dollyDelta.y > 0) {
                dollyIn(getZoomScale())
            } else if (dollyDelta.y < 0) {
                dollyOut(getZoomScale())
            }
            dollyStart.copy(dollyEnd);
            scope.update()
        }

        function handleMouseMovePan(event) {
            panEnd.set(event.clientX, event.clientY);
            panDelta.subVectors(panEnd, panStart);
            pan(panDelta.x, panDelta.y);
            panStart.copy(panEnd);
            scope.update()
        }

        function handleMouseUp(event) {
        }

        function handleMouseWheel(event) {
            var delta = 0;
            if (event.wheelDelta !== undefined) {
                delta = event.wheelDelta
            } else if (event.detail !== undefined) {
                delta = -event.detail
            }
            if (delta > 0) {
                dollyOut(getZoomScale())
            } else if (delta < 0) {
                dollyIn(getZoomScale())
            }
            scope.update()
        }

        function handleKeyDown(event) {
            switch (event.keyCode) {
                case scope.keys.UP:
                    pan(0, scope.keyPanSpeed);
                    scope.update();
                    break;
                case scope.keys.BOTTOM:
                    pan(0, -scope.keyPanSpeed);
                    scope.update();
                    break;
                case scope.keys.LEFT:
                    pan(scope.keyPanSpeed, 0);
                    scope.update();
                    break;
                case scope.keys.RIGHT:
                    pan(-scope.keyPanSpeed, 0);
                    scope.update();
                    break
            }
        }

        function handleTouchStartRotate(event) {
            rotateStart.set(event.touches[0].pageX, event.touches[0].pageY)
        }

        function handleTouchStartDolly(event) {
            var dx = event.touches[0].pageX - event.touches[1].pageX;
            var dy = event.touches[0].pageY - event.touches[1].pageY;
            var distance = Math.sqrt(dx * dx + dy * dy);
            dollyStart.set(0, distance)
        }

        function handleTouchStartPan(event) {
            panStart.set(event.touches[0].pageX, event.touches[0].pageY)
        }

        function handleTouchMoveRotate(event) {
            rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY);
            rotateDelta.subVectors(rotateEnd, rotateStart);
            var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
            rotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed);
            rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed);
            rotateStart.copy(rotateEnd);
            scope.update()
        }

        function handleTouchMoveDolly(event) {
            var dx = event.touches[0].pageX - event.touches[1].pageX;
            var dy = event.touches[0].pageY - event.touches[1].pageY;
            var distance = Math.sqrt(dx * dx + dy * dy);
            dollyEnd.set(0, distance);
            dollyDelta.subVectors(dollyEnd, dollyStart);
            if (dollyDelta.y > 0) {
                dollyOut(getZoomScale())
            } else if (dollyDelta.y < 0) {
                dollyIn(getZoomScale())
            }
            dollyStart.copy(dollyEnd);
            scope.update()
        }

        function handleTouchMovePan(event) {
            panEnd.set(event.touches[0].pageX, event.touches[0].pageY);
            panDelta.subVectors(panEnd, panStart);
            pan(panDelta.x, panDelta.y);
            panStart.copy(panEnd);
            scope.update()
        }

        function handleTouchEnd(event) {
        }

        function onMouseDown(event) {
            if (scope.enabled === false) {
                return
            }
            event.preventDefault();
            if (event.button === scope.mouseButtons.ORBIT) {
                if (scope.enableRotate === false) {
                    return
                }
                handleMouseDownRotate(event);
                state = STATE.ROTATE
            } else if (event.button === scope.mouseButtons.ZOOM) {
                if (scope.enableZoom === false) {
                    return
                }
                handleMouseDownDolly(event);
                state = STATE.DOLLY
            } else if (event.button === scope.mouseButtons.PAN) {
                if (scope.enablePan === false) {
                    return
                }
                handleMouseDownPan(event);
                state = STATE.PAN
            }
            if (state !== STATE.NONE) {
                document.addEventListener('mousemove', onMouseMove, false);
                document.addEventListener('mouseup', onMouseUp, false);
                document.addEventListener('mouseout', onMouseUp, false);
                scope.dispatchEvent(startEvent)
            }
        }

        function onMouseMove(event) {
            if (scope.enabled === false) {
                return
            }
            event.preventDefault();
            if (state === STATE.ROTATE) {
                if (scope.enableRotate === false) {
                    return
                }
                handleMouseMoveRotate(event)
            } else if (state === STATE.DOLLY) {
                if (scope.enableZoom === false) {
                    return
                }
                handleMouseMoveDolly(event)
            } else if (state === STATE.PAN) {
                if (scope.enablePan === false) {
                    return
                }
                handleMouseMovePan(event)
            }
        }

        function onMouseUp(event) {
            if (scope.enabled === false) {
                return
            }
            handleMouseUp(event);
            document.removeEventListener('mousemove', onMouseMove, false);
            document.removeEventListener('mouseup', onMouseUp, false);
            document.removeEventListener('mouseout', onMouseUp, false);
            scope.dispatchEvent(endEvent);
            state = STATE.NONE
        }

        function onMouseWheel(event) {
            if (scope.enabled === false || scope.enableZoom === false || (state !== STATE.NONE && state !== STATE.ROTATE)) {
                return
            }
            event.preventDefault();
            event.stopPropagation();
            handleMouseWheel(event);
            scope.dispatchEvent(startEvent);
            scope.dispatchEvent(endEvent)
        }

        function onKeyDown(event) {
            if (scope.enabled === false || scope.enableKeys === false || scope.enablePan === false) {
                return
            }
            handleKeyDown(event)
        }

        function onTouchStart(event) {
            if (scope.enabled === false) {
                return
            }
            switch (event.touches.length) {
                case 1:
                    if (scope.enableRotate === false) {
                        return
                    }
                    handleTouchStartRotate(event);
                    state = STATE.TOUCH_ROTATE;
                    break;
                case 2:
                    if (scope.enableZoom === false) {
                        return
                    }
                    handleTouchStartDolly(event);
                    state = STATE.TOUCH_DOLLY;
                    break;
                case 3:
                    if (scope.enablePan === false) {
                        return
                    }
                    handleTouchStartPan(event);
                    state = STATE.TOUCH_PAN;
                    break;
                default:
                    state = STATE.NONE
            }
            if (state !== STATE.NONE) {
                scope.dispatchEvent(startEvent)
            }
        }

        function onTouchMove(event) {
            if (scope.enabled === false) {
                return
            }
            event.preventDefault();
            event.stopPropagation();
            switch (event.touches.length) {
                case 1:
                    if (scope.enableRotate === false) {
                        return
                    }
                    if (state !== STATE.TOUCH_ROTATE) {
                        return;
                    }
                    handleTouchMoveRotate(event);
                    break;
                case 2:
                    if (scope.enableZoom === false) {
                        return
                    }
                    if (state !== STATE.TOUCH_DOLLY) {
                        return;
                    }
                    handleTouchMoveDolly(event);
                    break;
                case 3:
                    if (scope.enablePan === false) {
                        return
                    }
                    if (state !== STATE.TOUCH_PAN) {
                        return;
                    }
                    handleTouchMovePan(event);
                    break;
                default:
                    state = STATE.NONE
            }
        }

        function onTouchEnd(event) {
            if (scope.enabled === false) {
                return
            }
            handleTouchEnd(event);
            scope.dispatchEvent(endEvent);
            state = STATE.NONE
        }

        function onContextMenu(event) {
            event.preventDefault()
        }

        scope.domElement.addEventListener('contextmenu', onContextMenu, false);
        scope.domElement.addEventListener('mousedown', onMouseDown, false);
        scope.domElement.addEventListener('mousewheel', onMouseWheel, false);
        scope.domElement.addEventListener('MozMousePixelScroll', onMouseWheel, false);
        scope.domElement.addEventListener('touchstart', onTouchStart, false);
        scope.domElement.addEventListener('touchend', onTouchEnd, false);
        scope.domElement.addEventListener('touchmove', onTouchMove, false);
        window.addEventListener('keydown', onKeyDown, false);
        this.update()
    };
    THREE.OrbitControls.prototype = Object.create(THREE.EventDispatcher.prototype);
    THREE.OrbitControls.prototype.constructor = THREE.OrbitControls;
    Object.defineProperties(THREE.OrbitControls.prototype, {
        center: {
            get: function () {
                console.warn('THREE.OrbitControls: .center has been renamed to .target');
                return this.target
            }
        }, noZoom: {
            get: function () {
                console.warn('THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.');
                return !this.enableZoom
            }, set: function (value) {
                console.warn('THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.');
                this.enableZoom = !value
            }
        }, noRotate: {
            get: function () {
                console.warn('THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.');
                return !this.enableRotate
            }, set: function (value) {
                console.warn('THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.');
                this.enableRotate = !value
            }
        }, noPan: {
            get: function () {
                console.warn('THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.');
                return !this.enablePan
            }, set: function (value) {
                console.warn('THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.');
                this.enablePan = !value
            }
        }, noKeys: {
            get: function () {
                console.warn('THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.');
                return !this.enableKeys
            }, set: function (value) {
                console.warn('THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.');
                this.enableKeys = !value
            }
        }, staticMoving: {
            get: function () {
                console.warn('THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.');
                return !this.constraint.enableDamping
            }, set: function (value) {
                console.warn('THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.');
                this.constraint.enableDamping = !value
            }
        }, dynamicDampingFactor: {
            get: function () {
                console.warn('THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.');
                return this.constraint.dampingFactor
            }, set: function (value) {
                console.warn('THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.');
                this.constraint.dampingFactor = value
            }
        }
    });
</script>
<!-- 控制陀螺仪 （DeviceOrientationControls.js） -->
<script>
    THREE.DeviceOrientationControls = function (object) {
        var scope = this;
        this.object = object;
        this.object.rotation.reorder("YXZ");
        this.enabled = true;
        this.deviceOrientation = {};
        this.screenOrientation = 0;
        this.alpha = 0;
        this.alphaOffsetAngle = 0;
        var onDeviceOrientationChangeEvent = function (event) {
            scope.deviceOrientation = event
        };
        var onScreenOrientationChangeEvent = function () {
            scope.screenOrientation = window.orientation || 0
        };
        var setObjectQuaternion = function () {
            var zee = new THREE.Vector3(0, 0, 1);
            var euler = new THREE.Euler();
            var q0 = new THREE.Quaternion();
            var q1 = new THREE.Quaternion(-Math.sqrt(0.5), 0, 0, Math.sqrt(0.5));
            return function (quaternion, alpha, beta, gamma, orient) {
                euler.set(beta, alpha, -gamma, 'YXZ');
                quaternion.setFromEuler(euler);
                quaternion.multiply(q1);
                quaternion.multiply(q0.setFromAxisAngle(zee, -orient));
            }
        }();
        this.connect = function () {
            onScreenOrientationChangeEvent();
            window.addEventListener('orientationchange', onScreenOrientationChangeEvent, false);
            window.addEventListener('deviceorientation', onDeviceOrientationChangeEvent, false);
            scope.enabled = true
        };
        this.disconnect = function () {
            window.removeEventListener('orientationchange', onScreenOrientationChangeEvent, false);
            window.removeEventListener('deviceorientation', onDeviceOrientationChangeEvent, false);
            scope.enabled = false
        };
        this.update = function () {
            if (scope.enabled === false) {
                return
            }
            var alpha = scope.deviceOrientation.alpha ? THREE.Math.degToRad(scope.deviceOrientation.alpha) + this.alphaOffsetAngle : 0;
            var beta = scope.deviceOrientation.beta ? THREE.Math.degToRad(scope.deviceOrientation.beta) : 0;
            var gamma = scope.deviceOrientation.gamma ? THREE.Math.degToRad(scope.deviceOrientation.gamma) : 0;
            var orient = scope.screenOrientation ? THREE.Math.degToRad(scope.screenOrientation) : 0;
            setObjectQuaternion(scope.object.quaternion, alpha, beta, gamma, orient);
            this.alpha = alpha
        };
        this.updateAlphaOffsetAngle = function (angle) {
            this.alphaOffsetAngle = angle;
            this.update()
        };
        this.dispose = function () {
            this.disconnect()
        };
        this.connect()
    };
</script>
<!-- 代码 -->
<script>
    "use strict";
    (function (CanvasBody, _window) {
        var Scene = void 0,
            Camera = void 0,
            Renderer = void 0,
            FpsStats = void 0,
            AnimateFrame = void 0,
            Controls = void 0,
            Devices = void 0; // 场景，照相机，渲染器，FPS监视器，渲染定时器，控制器，陀螺仪
        var onDevice = document.getElementById("onDevice");
        var isDeviceing = 0; // 陀螺仪状态
        /* 初始化函数 */

        // 初始化场景
        function initScene() {
            Scene = new THREE.Scene();
        }

        // 初始化照相机
        function initCamera() {
            Camera = new THREE.PerspectiveCamera(60, CanvasBody.clientWidth / CanvasBody.clientHeight, 1, 3000);
            Camera.position.set(1, 0, 0);
            Camera.lookAt({x: 200, y: 0, z: 0});
        }

        // 初始化渲染器
        function initRenderer() {
            Renderer = new THREE.WebGLRenderer();
            Renderer.setSize(CanvasBody.clientWidth, CanvasBody.clientHeight);
            Renderer.setClearColor(0x000000, 1);
            CanvasBody.appendChild(Renderer.domElement);
        }

        // 初始化监视器
        function initFpsStats() {
            FpsStats = new Stats();
            CanvasBody.appendChild(FpsStats.domElement);
            FpsStats.domElement.style.cssText = "position: absolute;top: 0;left: 0;";
        }

        // 初始化控制器
        function initControls() {
            Controls = new THREE.OrbitControls(Camera);
        }

        // 初始化陀螺仪
        function initDevices() {
            Devices = new THREE.DeviceOrientationControls(Camera);
        }

        /* 窗口改变事件 */
        function windowChange() {
            initCamera();
            Renderer.setSize(CanvasBody.clientWidth, CanvasBody.clientHeight);
            initDevices();
            initControls();
        }

        /* 控制陀螺仪 */
        function controlDevice(event) {
            if (isDeviceing === 0) {
                isDeviceing = 1;
                onDevice.value = "关闭陀螺仪";
            } else {
                isDeviceing = 0;
                onDevice.value = "开启陀螺仪";
            }
        }

        /* 动画 */
        function animate(time) {
            FpsStats.begin();
            Renderer.clear();
            isDeviceing === 0 ? Controls.update() : Devices.update();
            Renderer.render(Scene, Camera);
            FpsStats.end();
            AnimateFrame = requestAnimationFrame(animate);
        }

        /* 初始化 */
        function init() {
            // 初始化
            initScene();
            initCamera();
            initRenderer();
            initFpsStats();
            initControls();
            initDevices();
            // 初始化绑定陀螺仪
            Devices.connect();
            _window.addEventListener("resize", windowChange, false);
            onDevice.addEventListener("click", controlDevice, false);
            AnimateFrame = requestAnimationFrame(animate);
        }

        init();
        /* 场景内物体 */
        (function () {
            var r = Math.sqrt(5000 * 1827 / 4 / Math.PI);
            var texture = THREE.ImageUtils.loadTexture("demo.jpg", {}, function () {
                var geometry = new THREE.SphereGeometry(r, 100, 100);
                var material = new THREE.MeshLambertMaterial({
                    map: texture,
                    side: THREE.DoubleSide
                });
                var mesh = new THREE.Mesh(geometry, material);
                Scene.add(mesh);
                mesh.position.set(0, 0, 0);

                var al = new THREE.AmbientLight(0xffffff);
                Scene.add(al);
            });
        })();
    })(document.getElementById("CanvasBody"), window);
</script>
</body>
</html>